﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Tetris.Grid
{
    public class GridPosition
    {
        public static GridPosition Zero = new GridPosition(0, 0);

        private Tuple<int, int> m_gridPosition;
        public int col
        {
            get
            {
                return m_gridPosition.Item1;
            }
        }
        public int row
        {
            get
            {
                return m_gridPosition.Item2;
            }
        }

        public GridPosition(int col, int row)
        {
            m_gridPosition = new Tuple<int, int>(col, row);
        }

        public Vector2 AsVector()
        {
            return new Vector2(this.col, this.row);
        }

        public GridPosition Rotate(bool clockWise, GridPosition origin)
        {
            /**
             * The idea: Rotation Matrices using the difference (offset) between this grid position and the origin
             * To rotate a vector 90 degrees about its origin:
             *      counter-clockwise => theta = 90 degrees:
             *          cos(theta)  -sin(theta)             0   -1
             *                                      =       
             *          sin(theta)  cos(theta)              1   0  
             *      Thus we have 
             *          x' = -y
             *          y' = x
             * 
             *      clockwise => theta = -90 degrees:
             *          cos(theta)  sin(theta)              0   1
             *                                      =       
             *          -sin(theta)  cos(theta)             -1  0
             *      Thus we have 
             *          x' = y
             *          y' = -x
             */
            GridPosition offset = this - origin;
            if (offset == GridPosition.Zero)
                return this;

            GridPosition rotatedOffset;
            if (clockWise)
            {
                rotatedOffset = new GridPosition(-offset.row, offset.col);
            }
            else
            {
                rotatedOffset = new GridPosition(offset.row, -offset.col);
            }

            return rotatedOffset + origin;
        }

        public static GridPosition operator +(GridPosition gp1, GridPosition gp2)
        {
            return new GridPosition(gp1.col + gp2.col, gp1.row + gp2.row);
        }

        public static GridPosition operator -(GridPosition gp1, GridPosition gp2)
        {
            return new GridPosition(gp1.col - gp2.col, gp1.row - gp2.row);
        }

        public static bool operator ==(GridPosition gp1, GridPosition gp2)
        {
            // If both are null, or both are same instance, return true.
            if (System.Object.ReferenceEquals(gp1, gp2))
            {
                return true;
            }

            return (gp1.col == gp2.col) && (gp1.row == gp2.row);
        }

        public static bool operator !=(GridPosition gp1, GridPosition gp2)
        {
            return !(gp1 == gp2);
        }

        public override bool Equals(object obj)
        {
            return obj is GridPosition && this == (GridPosition)obj;
        }

        public override int GetHashCode()
        {
            return this.col.GetHashCode() ^ this.row.GetHashCode();
        }
    }
}
